
#include <iostream>
using namespace std;
int Bits(int m, int n, int c){return ((c >> n) & ~(-2 << (m - n)));}
int E(int x){return ((x <= 0x19) ? (x + 0x41) : ((x <= 0x33) ? (x + 0x47) : ((x <= 0x3D) ? (x - 0x4) : ((x == 0x3E) ? 0x2B : 0x2F))));}

char* Base64Encoder(const char* input, int len){
    char* output = new char[(len * 2) + 3];
    int r0 = 0;int state = 0;
    int pos = 0;
    for (int i = 0; i < len; i++){
        int c = (int)input[i];
        switch (state){
        case (0): {
            if (!(Bits(7,0,c)==c)) {
                throw ("InvalidCharacter");
            } else {
                output[pos++] = ((char)E(Bits(15,2,c)));r0 = (Bits(1,0,c)<<4);state = 1;
            }
            break;}
        case (1): {
            if (!(Bits(7,0,c)==c)) {
                throw ("InvalidCharacter");
            } else {
                output[pos++] = ((char)E(r0|Bits(15,4,c)));r0 = (Bits(3,0,c)<<2);state = 2;
            }
            break;}
        case (2): {
            if (!(Bits(7,0,c)==c)) {
                throw ("InvalidCharacter");
            } else {
                output[pos++] = ((char)E(r0|Bits(15,6,c)));output[pos++] = ((char)E(Bits(5,0,c)));r0 = 0;state = 0;
            }
            break;}
        default: {
            throw ("Base64Encoder");
                 }
        }
    }
    switch (state){
    case (0): {

        break;}
    case (1): {
        output[pos++] = ((char)E(r0));output[pos++] = ((char)0x3D);output[pos++] = ((char)0x3D);
        break;}
    case (2): {
        output[pos++] = ((char)E(r0));output[pos++] = ((char)0x3D);
        break;}
    default: {
        throw ("Base64Encoder");
             }
    }
    return output;
}
